package com.bnzj.cloud.business.core.web;

import com.bnzj.cloud.business.core.persistence.entity.SysRole;
import com.bnzj.cloud.business.core.persistence.entity.SysRoleResource;
import com.bnzj.cloud.business.core.persistence.entity.SysRoleUser;
import com.bnzj.cloud.business.core.persistence.entity.SysUser;
import com.bnzj.cloud.business.core.service.SysResourceRoleService;
import com.bnzj.cloud.business.core.service.SysRoleService;
import com.bnzj.cloud.business.core.service.SysRoleUserService;
import com.bnzj.core.action.ActionType;
import com.bnzj.core.action.annotation.Action;
import com.bnzj.core.exception.BusinessException;
import com.bnzj.core.persistence.query.CompareExpression;
import com.bnzj.core.persistence.query.CompareType;
import com.bnzj.core.persistence.query.IExpression;
import com.bnzj.core.persistence.query.QueryHelpBean;
import com.bnzj.core.persistence.util.EntityUtils;
import com.bnzj.core.rest.CurrentUserService;
import com.bnzj.core.rest.ResponseResult;
import com.bnzj.core.rest.ResultCode;
import com.bnzj.core.rest.UserInfo;
import com.bnzj.core.util.BeanUtils;
import com.bnzj.core.util.FbConstant;
import com.bnzj.core.util.SpringUtils;
import com.bnzj.core.webmvc.util.WebMvcUtils;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Optional;

/**
 * @author Barry
 * @createDate 2020/2/13
 * @description
 */
@Tag(name = "角色", description = "角色管理：角色新增删除更新查询等")
@RestController
@RequestMapping("/system/role")
public class SysRoleController {

    @Autowired
    private CurrentUserService gatewayCurrentUserService;

    @Autowired
    private SysRoleUserService sysRoleUserService;

    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysResourceRoleService sysResourceRoleService;

    @Operation(summary = "分页查询", description = "角色分页查询默认 是第1页 分页大小为10",
            parameters = {
                    @Parameter(name = "enabled", description = "管理员可用：启用1禁用0", allowEmptyValue = true, allowReserved = true,
                            schema = @Schema(type = "int", description = "int")),
                    @Parameter(name = "keyWord", description = "根据名称和编码模糊", allowEmptyValue = true, allowReserved = true,
                            schema = @Schema(implementation = String.class, description = "根据名称和编码模糊查"))})
    @GetMapping(value = "/page")
    public ResponseResult<Page<SysRole>> getRolePage(HttpServletRequest request, @RequestParam(value = "enabled", required = false) Boolean enabled) {
        Pageable pageable = WebMvcUtils.initPage(request, Sort.by(Sort.Direction.DESC, "create_time"));
        QueryHelpBean queryHelpBean = SysRoleService.getQueryHelpBean();
        queryHelpBean.setPageable(pageable);
        IExpression andCondition = CompareExpression.build("r.enabled", CompareType.equal, enabled);
        String keyWord = request.getParameter("keyWord");
        IExpression orCondition1 = CompareExpression.build("r.name", CompareType.like, keyWord);
        IExpression orCondition2 = CompareExpression.build("r.code", CompareType.like, keyWord);
        queryHelpBean.addWhere(andCondition.and(orCondition1.or(orCondition2)));
        Page<SysRole> all = sysRoleService.findAll(queryHelpBean);
        return ResponseResult.success(all);
    }

    @Operation(summary = "根据id查询")
    @GetMapping("/one/{id}")
    public ResponseResult<SysRole> getById(@Parameter(name = "id", in = ParameterIn.PATH, description = "主键", required = true) @PathVariable("id") Long id) {
        Optional<SysRole> optional = sysRoleService.findById(id);
        return ResponseResult.success(optional.orElse(null));
    }

    @Operation(summary = "根据code查询")
    @GetMapping("/code/{code}")
    public ResponseResult<SysRole> getByCode(@Parameter(in = ParameterIn.PATH, description = "角色编码", required = true, name = "code") @PathVariable String code) {
        SysRole sysRole = sysRoleService.findByCode(code);
        if (ObjectUtils.isEmpty(sysRole)) {
            throw new BusinessException(ResultCode.getResultCode(ResultCode.RESOURCE_NOT_EXIST));
        }
        return ResponseResult.success(sysRole);
    }

    @Operation(summary = "获取所有角色编码")
    @GetMapping("/codes")
    public ResponseResult<List<String>> findAllCode() {
        List<String> allCode = sysRoleService.findAllCode();
        if (CollectionUtils.isEmpty(allCode)) {
            throw new BusinessException(ResultCode.getResultCode(ResultCode.RESOURCE_NOT_EXIST));
        }
        return ResponseResult.success(allCode);
    }

    @Operation(summary = "保存")
    @PostMapping("/save")
    @Action(descriprion = "角色保存", moduleName = "角色", operateType = ActionType.ADD_DATA)
    public ResponseResult<?> addRole(@RequestBody
                                     @Valid SysRole role) {
        UserInfo userInfo = gatewayCurrentUserService.getUserInfo();
        EntityUtils.saveBefore(role, userInfo.getAccount(), userInfo.getName());
        sysRoleService.save(role);
        return ResponseResult.success();
    }

    @Operation(summary = "更新")
    @Action(descriprion = "角色更新", moduleName = "角色", operateType = ActionType.UPDATE_DATA)
    @PostMapping("/update")
    public ResponseResult<?> updateRole(@RequestBody SysRole role) {
        if (ObjectUtils.isEmpty(role.getId())) {
            throw new BusinessException(ResultCode.getResultCode(ResultCode.BAD_REQUEST));
        }
        UserInfo userInfo = gatewayCurrentUserService.getUserInfo();
        Optional<SysRole> byId = sysRoleService.findById(role.getId());
        if (!byId.isPresent()) {
            throw new BusinessException(ResultCode.getResultCode(ResultCode.RESOURCE_NOT_EXIST));
        }
        SysRole sysRoleDb = byId.get();
        BeanUtils.copyProperties(role, sysRoleDb);
        EntityUtils.saveBefore(sysRoleDb, userInfo.getAccount(), userInfo.getName());
        sysRoleService.save(sysRoleDb);
        return ResponseResult.success();
    }

    /**
     * 启用禁用
     *
     * @param id 主键，type 1启动 0禁用
     * @return
     */
    @Operation(summary = "启用禁用")
    @PostMapping(value = {"/disable/{id}/{type}", "/enable/{id}/{type}"})
    public ResponseResult<?> disabled(@Parameter(in = ParameterIn.PATH, description = "主键", required = true, name = "id") @PathVariable("id") Long id,
                                      @Parameter(in = ParameterIn.PATH, description = "启用1禁用0", required = true, name = "type") @PathVariable("type") Short type) {
        Short status = FbConstant.DB_DISABLE.equals(type) ? FbConstant.DB_DISABLE : FbConstant.DB_ENABLE;
        sysRoleService.updateEnabled(status, id);
        return ResponseResult.success();
    }

    /**
     * @param list 给角色授权资源
     * @return com.bnzj.core.rest.ResponseResult
     * @depict
     * @auth Barry
     * @createDate 2020/2/20
     * @updateAuthOrOther
     */
    @Operation(summary = "角色授权", description = "给角色授权资源")
    @PostMapping(value = {"/permission/resource/{roleId}"})
    public ResponseResult<?> permissionAssignment(@RequestBody List<SysRoleResource> list,
                                                  @Parameter(name = "roleId", description = "角色id", schema = @Schema(name = "roleId", type = "long")) @PathVariable(value = "roleId", required = true) Long roleId) {
        SysResourceRoleService sysResourceRoleService = SpringUtils.get(SysResourceRoleService.class);
        sysResourceRoleService.addOrEditJuri(list, roleId);
        return ResponseResult.success();
    }

    /**
     * @param list
     * @return com.bnzj.core.rest.ResponseResult
     * @depict 给用户授权角色
     * @auth Barry
     * @createDate 2020/2/20
     * @updateAuthOrOther
     */
    @Operation(summary = "角色用户授权", description = "给用户授权角色")
    @PostMapping(value = {"/permission/user/{roleId}"})
    public ResponseResult<?> roleAssignmentUser(@RequestBody List<SysRoleUser> list,
                                                @Parameter(name = "roleId", description = "角色id", schema = @Schema(name = "roleId", type = "long")) @PathVariable(value = "roleId", required = true) Long roleId) {
        sysRoleUserService.portionUser(list, roleId);
        return ResponseResult.success();
    }

    @GetMapping("/resources/{id}")
    public ResponseResult<List<Long>> getTheResourceCollectionByRoleId(@PathVariable("id") Long roleId) {
        List<Long> coll = sysResourceRoleService.getTheResourceCollectionByRoleId(roleId);
        return ResponseResult.success(coll);
    }

    @Operation(summary = "获取该角色下所有用户", description = "根据主键获取该角色下所有用户")
    @GetMapping("/users/{id}")
    public ResponseResult<List<SysUser>> getUserByRoleId(
            @Parameter(in = ParameterIn.PATH, name = "id", required = true, description = "主键") @PathVariable("id") Long roleId) {
        List<SysUser> coll = sysRoleUserService.getUsersByRoleId(roleId);
        return ResponseResult.success(coll);
    }

    @Operation(summary = "获取该角色下所有基础用户", description = "根据主键获取该角色下所有基础用户")
    @GetMapping("/base/users/{id}")
    public ResponseResult<List<SysUser>> getBaseUsersByRoleId(
            @Parameter(in = ParameterIn.PATH, name = "id", required = true, description = "主键") @PathVariable("id") Long roleId) {
        List<SysUser> coll = sysRoleUserService.getBaseUsersByRoleId(roleId);
        return ResponseResult.success(coll);
    }

    //根据角色code查询拥有该角色的用户的账号
    @Hidden
    @GetMapping("/{roleCode}/accounts")
    public String getAccountsByRoleCode(@PathVariable("roleCode") String roleCode) {
        return sysRoleUserService.findAccountsByRoleCode(roleCode);
    }
}
